///////////////////////////////////////////////////////////////////////
//
// NO_Type.h
//
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
#ifndef NO_ITYPE_INFO_H
#define NO_ITYPE_INFO_H

///////////////////////////////////////////////////////////////////////
#include "NO_Base.h"
#include "NO_Scope.h"
#include "NO_Member.h"
#include "NO_StaticFunction.h"
#include "NO_MemberFunction.h"
#include "NO_Referencer.h"
#include "NO_Transform.h"
#include "NO_Constructor.h"
#include "NO_Definition.h"
#include "NO_Includes.h"

//////////////////////////////////////////////////////////////////////////
class NO_HelperTypeID;
class NO_Type;

//////////////////////////////////////////////////////////////////////////
// TypeHandler
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_TypeHandler
{
public:
	//////////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	NO_TypeHandler();
	~NO_TypeHandler();

	//////////////////////////////////////////////////////////////////////////
	// modify
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	void setTypePtrToControl(NO_Type*&);

private:		
	//////////////////////////////////////////////////////////////////////////
	// friends
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////
	friend class NO_Type;

	//////////////////////////////////////////////////////////////////////////
	NO_Type** toCtrl;
	NO_Int32 id;
};

//////////////////////////////////////////////////////////////////////////
// NO_Type
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_Type
{
protected:
	//////////////////////////////////////////////////////////////////////////
	typedef std::map<type_info const *, NO_Type*>	InternTypes;
	typedef NO_IDSet<NO_Type,2>						GlobalTypes;
	typedef std::vector<NO_TypeHandler*>			TypeHandlers;
	typedef std::list<NO_UInt32 >					FreeList;
	
public:
	//////////////////////////////////////////////////////////////////////////
	typedef InternTypes::const_iterator	InternTypeIter;
	typedef GlobalTypes::const_iterator	GlobalTypeIter;
	
	//////////////////////////////////////////////////////////////////////////
	// retrieve 
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////
	NO_UInt32		 getID(void)		const;
	NO_Boolean		 getIsValid(void)	const;
	const NO_Plugin* getPlugin(void)	const;

	//////////////////////////////////////////////////////////////////////////
	virtual std::type_info const &	getRTTI(void)		const = 0;
	virtual std::string	const &		getName(void)		const = 0;
	virtual NO_UInt32				getSize(void)		const = 0;
	virtual NO_UInt32				getTypeCode(void)	const = 0;

	//////////////////////////////////////////////////////////////////////////
	// retrieve
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type*			findType		(NO_Int8 const * name)							const = 0;
	virtual const NO_IBase*			findBase		(NO_Int8 const * name)							const = 0;
	virtual const NO_IMember*		findMember		(NO_Int8 const * name)							const = 0;
	virtual const NO_IFunction*		findFunction	(NO_Int8 const * name, NO_TypeList& parameter)	const = 0;
	virtual const NO_IConstructor*	findConstructor	(NO_TypeList& parameter)						const = 0;
	
	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type*			findType		(NO_UInt32 ID) const = 0;
	virtual const NO_IBase*			findBase		(NO_UInt32 ID) const = 0;
	virtual const NO_IMember*		findMember		(NO_UInt32 ID) const = 0;
	virtual const NO_IFunction*		findFunction	(NO_UInt32 ID) const = 0;
	virtual const NO_IConstructor*	findConstructor	(NO_UInt32 ID) const = 0;
	
	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type*			beginType		(void) const = 0;
	virtual const NO_IBase*			beginBase		(void) const = 0;
	virtual const NO_IMember*		beginMember		(void) const = 0;
	virtual const NO_IFunction*		beginFunction	(void) const = 0;
	virtual const NO_IConstructor*	beginConstructor(void) const = 0;
	
	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type*			endType			(void) const = 0;
	virtual const NO_IBase*			endBase			(void) const = 0;
	virtual const NO_IMember*		endMember		(void) const = 0;
	virtual const NO_IFunction*		endFunction		(void) const = 0;
	virtual const NO_IConstructor*	endConstructor	(void) const = 0;
	
	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type*			nextType		(const NO_Type*)		const = 0;
	virtual const NO_IBase*			nextBase		(const NO_IBase*)		const = 0;
	virtual const NO_IMember*		nextMember		(const NO_IMember *)	const = 0;
	virtual const NO_IFunction*		nextFunction	(const NO_IFunction*)	const = 0;
	virtual const NO_IConstructor*	nextConstructor	(const NO_IConstructor*)const = 0;

	//////////////////////////////////////////////////////////////////////////
	// use
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	virtual NO_OArchive&	output (NO_Object&, NO_OArchive&) const = 0;
	virtual NO_IArchive&	input  (NO_Object&, NO_IArchive&) const = 0;
	
	//////////////////////////////////////////////////////////////////////////
	// operators
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////
	bool operator==(const NO_Type& rhs) const;
	bool operator!=(const NO_Type& rhs) const;
	
protected:
	//////////////////////////////////////////////////////////////////////////
	// friends
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////
	friend class NO_ReferencerFriendHelper;
	friend class NO_HelperTypeID;
	friend class NO_TypeHandler;
	friend class NO_TypeFriend;
	friend class NO_IArchive;
	friend class NO_Plugin;
	friend class NO_Object;
	friend class NO_Scope;
	
	//////////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////
	NO_Type(NO_Plugin&);
	virtual ~NO_Type(void);
	
	//////////////////////////////////////////////////////////////////////////
	// retrieve
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	virtual NO_Value* getElement		(NO_Value&, NO_UInt32)			const = 0;
	virtual NO_Value* getCopy			(NO_Value&)						const = 0;
	virtual NO_Value* getReplace		(NO_UInt32)						const = 0;
	virtual NO_Value* getReflect		(NO_Value&, void*, NO_UInt32)	const = 0;
	virtual NO_Value* getReference		(NO_Value&)						const = 0;
	virtual NO_Value* getDereference	(NO_Value&)						const = 0; 
	
	//////////////////////////////////////////////////////////////////////////
	// static
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////
	static NO_Boolean		addIntern	  (NO_Type& type);
	static NO_Boolean		remIntern	  (NO_Type& type);
	static InternTypeIter	beginIntern	  (void);
	static InternTypeIter	endIntern	  (void);
	static InternTypeIter	nextIntern	  (InternTypeIter);
	static InternTypeIter	findIntern	  (type_info const & rtti);
	
	//////////////////////////////////////////////////////////////////////////
	static NO_Boolean		addGlobal	(NO_Type& type);
	static NO_Boolean		remGlobal	(NO_Type& type);
	static GlobalTypeIter	beginGlobal	(void);
	static GlobalTypeIter	endGlobal	(void);
	static GlobalTypeIter	nextGlobal	(GlobalTypeIter);
	static GlobalTypeIter	findGlobal	(NO_Int8 const * name);
	static GlobalTypeIter	findGlobal	(NO_UInt32 ID);

	//////////////////////////////////////////////////////////////////////////
	void registerHandler	(NO_TypeHandler&);
	void unRegisterHandler	(NO_TypeHandler&);
	
protected:
	//////////////////////////////////////////////////////////////////////////
	NO_UInt32 id;
	
	//////////////////////////////////////////////////////////////////////////
	static InternTypes	interns;
	static GlobalTypes	globals;
	
private:		
	//////////////////////////////////////////////////////////////////////////
	NO_Plugin*		plugin;
	TypeHandlers	typeHandlers;
	FreeList		freeHandlers;
	NO_Type*		next;
};

/////////////////////////////////////////////////////////////////////////
//
// NO_TypeImpl class template
//
//////////////////////////////////////////////////////////////////////////
template<class T,
		 NO_UInt32 TypeCode,
		 class SizePolicy = NO_NoneSizing,
		 class NamePolicy = NO_NoneNaming,
		 class DefinitionPolicy = NO_NoneDefinition,
		 class ReferencPolicy = NO_NoneReferencer,
		 class TransformPolicy = NO_NoneTransform,		
		 class ConstructionPolicy = NO_NoneConstructors,
		 class CopyPolicy	= NO_NoneCopy,
		 class MemberPolicy = NO_NoneMembers,
		 class FunctionPolicy = NO_NoneFunctions,
		 class BasePolicy = NO_NoneBases,
		 class TypePolicy = NO_NoneScope>
class NO_TypeImp : public NO_Type
				 , public CopyPolicy
				 , public BasePolicy
				 , public TypePolicy
				 , public NamePolicy
				 , public SizePolicy
				 , public MemberPolicy
				 , public FunctionPolicy
				 , public ReferencPolicy
				 , public TransformPolicy
				 , public DefinitionPolicy
				 , public ConstructionPolicy
{
public:
	//////////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	static NO_TypeImp& define(const NO_Int8* name, NO_Plugin& plug)
	{
		InternTypeIter iter = NO_Type::findIntern(typeid(T));
		if(iter!=NO_Type::endIntern()){std::exception("Type already defined");}

		return (*(new NO_TypeImp(name,plug)));
	}

private:
	//////////////////////////////////////////////////////////////////////////
	// retrieve 
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////
	virtual std::type_info const &	getRTTI			(void) const {return typeid(T);}
	virtual std::string const &		getName			(void) const {return getNameImpl();}
	virtual NO_UInt32				getSize			(void) const {return getSizeImpl();}
	virtual NO_UInt32				getTypeCode		(void) const {return TypeCode;}

	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type*			findType		(const NO_Int8* n)					const{return findTypeImpl(n);}
	virtual const NO_IBase *		findBase		(const NO_Int8* n)					const{return findBaseImpl(n);}
	virtual const NO_IMember *		findMember		(const NO_Int8* n)					const{return findMemberImpl(n);}
	virtual const NO_IFunction *	findFunction	(const NO_Int8* n, NO_TypeList& p)	const{return findFunctionImpl(n,p);}
	virtual const NO_IConstructor *	findConstructor	(NO_TypeList& p)					const{return findConstructorImpl(p);}
	
	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type*			findType		(NO_UInt32 ID) const {return findTypeImpl(ID);}
	virtual const NO_IBase *		findBase		(NO_UInt32 ID) const {return findBaseImpl(ID);}
	virtual const NO_IMember *		findMember		(NO_UInt32 ID) const {return findMemberImpl(ID);}
	virtual const NO_IFunction *	findFunction	(NO_UInt32 ID) const {return findFunctionImpl(ID);}
	virtual const NO_IConstructor *	findConstructor	(NO_UInt32 ID) const {return findConstructorImpl(ID);}
	
	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type*			beginType		(void) const {return beginTypeImpl();}
	virtual const NO_IBase*			beginBase		(void) const {return beginBaseImpl();}
	virtual const NO_IMember *		beginMember		(void) const {return beginMemberImpl();}
	virtual const NO_IFunction*		beginFunction	(void) const {return beginFunctionImpl();}
	virtual const NO_IConstructor*	beginConstructor(void) const {return beginConstructorImpl();}
	
	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type*			endType			(void) const {return endTypeImpl();}
	virtual const NO_IBase*			endBase			(void) const {return endBaseImpl();}
	virtual const NO_IMember *		endMember		(void) const {return endMemberImpl();}
	virtual const NO_IFunction*		endFunction		(void) const {return endFunctionImpl();}
	virtual const NO_IConstructor*	endConstructor	(void) const {return endConstructorImpl();}
	
	//////////////////////////////////////////////////////////////////////////
	virtual const NO_Type*			nextType		(const NO_Type* i)			const {return nextTypeImpl(i);}
	virtual const NO_IBase*			nextBase		(const NO_IBase* i)			const {return nextBaseImpl(i);}
	virtual const NO_IMember *		nextMember		(const NO_IMember * i)		const {return nextMemberImpl(i);}
	virtual const NO_IFunction*		nextFunction	(const NO_IFunction* i)		const {return nextFunctionImpl(i);}
	virtual const NO_IConstructor*	nextConstructor	(const NO_IConstructor* i)	const {return nextConstructorImpl(i);}

	//////////////////////////////////////////////////////////////////////////
	// use
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	virtual NO_OArchive&	output (NO_Object& o, NO_OArchive& a) const {return outputImpl(o,a);}
	virtual NO_IArchive&	input  (NO_Object& o, NO_IArchive& a) const {return inputImpl(o,a);}
	
	//////////////////////////////////////////////////////////////////////////
	virtual NO_Value* getElement		(NO_Value& d, NO_UInt32 n)			const {return getElementImpl(d,n);}
	virtual NO_Value* getReference		(NO_Value& d)						const {return getReferenceImpl(d);}
	virtual NO_Value* getDereference	(NO_Value& d)						const {return getDereferenceImpl(d);}
	virtual NO_Value* getReflect		(NO_Value& d, void* o, NO_UInt32 n)	const {return getReflectImpl(d,o,n);}
	virtual NO_Value* getReplace		(NO_UInt32 n)						const {return getReplaceImpl(n);}
	virtual NO_Value* getCopy			(NO_Value& d)						const {return getCopyImpl(d);}

private:
	//////////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	NO_TypeImp(const NO_Int8* n, NO_Plugin& p):NO_Type(p)
	{
		id = noGetHash(n);
		setNameImpl(n);
		defineImpl(n,p);
		if(!addGlobal(*this)){std::exception("Type failed to add to global list.");}
		if(!addIntern(*this)){std::exception("Type failed to add to local list.");}		
	}
	
	//////////////////////////////////////////////////////////////////////////
	virtual ~NO_TypeImp()
	{
		remGlobal(*this);	
		remIntern(*this);	
	}
};

#endif

